/**
 * @constructor Archetype.Tools.URL
 */
$N("Archetype.Tools.URL", Archetype.Class.create({

    initialize: function (_urlString) {
        return this.parse(_urlString);
    },

    parse: function(_urlString) {
        this.urlString = _urlString || window.location.href;
        var uriArray = $A(this.urlString.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)([#?]{1}.*)?$/))||[];

        //console.debug("uriArray", uriArray);
        // URI basic parts
        this.scheme = uriArray[2];
        this.authority = uriArray[4];
        this.path = uriArray[5];
        this.queryOrFragment = uriArray[6];

        // URL basic parts
        this.protocol = this.scheme;
        var parsedAuthority = this.authority.match(/^(([^:@]*):?([^@]*?)@)?([^:\/]*)(:([0-9]*?))?$/);
        //console.debug("parsedAuthority",parsedAuthority);
        // foo
        this.login = parsedAuthority[2] ||"";
        // bar
        this.password = parsedAuthority[3] ||"";
        // localhost, 127.0.0.1, archetypejs.org
        this.host = parsedAuthority[4];
        // 80, 443, 8080
        this.port = parsedAuthority[6] !== undefined ? parsedAuthority[6] : (this.protocol=="https" ? "443" : "80");
        // /foo/bar/bar.html
        this.fullPath = parsedAuthority[9] || "";
        var pathInfo = this.fullPath.match(/^(.*\/)(.*?)$/)||[];

        // /foo/bar/
        this.path=pathInfo[1];
        // bar.html
        this.resource=pathInfo[2];




        var urlEnd = this.queryOrFragment || "";
        //this.queryPath=$A(urlEnd.match(/^.*?\?(([^#]+)\/([^#]*))+($|\#.*$)/));
        // ?...
        this.queryString =       $A(urlEnd.match(/^.*?\?([^#]+)($|\#.*$)/))[1] || "";
        // #...
        this.fragmentString =    $A(urlEnd.match(/^.*?\#([^?]+)($|\?.*$)/))[1] || "";

        this.query = $H(this.queryString.toQueryParams());
        this.fragment = $H(this.fragmentString.toQueryParams());
        this.anyParam = $H(this.query).merge(this.fragment);

        this.queryPath =     $A(urlEnd.match(/^.*?\?(([^#]+)\/([^#]+)\/)+($|\#.*$)/)) || "";
        this.targetPath =    $A(urlEnd.match(/^.*?\#(([^?]+)\/([^?]+)\/)+($|\?.*$)/)) || "";
        var queryPathParameterArrays = this.queryPath.partition(function(e,i) {return 0 == i % 2;});
        var targetPathParameterArrays =  this.queryPath.partition(function(e,i) {return 0 == i % 2;});
        this.queryPathParameters = {};
        queryPathParameterArrays[0].each(function(key,i) {
            this.queryPathParameters[key] = queryPathParameterArrays[1][i]
        });
        this.targetPathParameters = {};
        targetPathParameterArrays[0].each(function(key,i) {
            this.targetPathParameters[key] = targetPathParameterArrays[1][i]
        });
        this.anyPathParameters = $H(this.queryPathParameters).merge(this.targetPathParameters);

        // ?foo
        this.queryState = this.hasQuery() ? "" : this.queryString;
        // #bar
        this.fragmentState = this.hasFragment() ? "" : this.fragmentString;
        // ?foo or #foo
        this.anyParamState = this.hasAnyParameter() ? "" : this.fragmentString||this.queryString;
        return this;
    },
    hasQuery: function () {
        return this.query.values().compact().size() > 0;
    },
    hasFragment: function () {
        return this.fragment.values().compact().size() > 0;
    },
    hasAnyParameter: function () {
        return this.hasQuery() || this.hasFragment();
    },
    hasTarget: function () {
        return this.fragmentString.length > 0;
    },
    toString: function() {
        return this.urlString;
    }
}));


